console.log('hello ts')
let age:number = 22
console.log(age)

let count: number = 20
count.toFixed()

let a: undefined = undefined
a = undefined

let number: number[] = [1,2,4,5]
let string: string[] = ['3','2']
let boolean: boolean[]= [false,true,false]
let abc: Array<string> = ['f','s','d']

// 联合类型
let arr: (number | string | boolean)[] = [1,'d',false]
let b: (undefined | string) = undefined
b = '2b'
let c: (number | string[]) = ['a','d']
c = 123

// 类型别名
type CustomArray = (number | string)[]
let dd: CustomArray = [12,3,'ggsg','dff']
let obj: object = {a:1,b:3,v:'adfd'}
type objArray = Object[]
let objArray: objArray = [obj]

// 函数返回值类型以及参数类型
function add(num1: number,num2: number):number{
    return num1+num2
}

function concat(num: number, string: string):string{
    return num+string
}

// 同时指定返回值和参数类型
type addType = (num1: number,num2: number) => number
let add1: addType = (a,b)=>{
    return a+b
}

// 函数返回值空类型
function show(a: number,b: string) :void{
    console.log(a,b)
}

// 函数可选参数
// 可选参数后面不能再有必选参数
function out(a?: number,b?: boolean): void{
    if(b){
        console.log(a)
    }
}

// 对象类型
let person: { name: string, age: number, sayHi(): void } = {
    name:'zhangyang',
    age:22,
    sayHi(){
        console.log('Hi!')
    }
}

// 接口，用于对象
interface IPerson {
    name: string,
    age?: number,
    sayHi(): void
}
// 以上等同于   (有等号)
type IPerson1 = {
    name: string,
    age?: number,
    sayHi(): void
}

let person2: IPerson = {
    name:'zhengmengting',
    sayHi() {
        console.log('hello')
    },
}

// 接口的继承
interface Point2D {
    x: number,
    y: number
}

interface Point3D extends Point2D {
    z: number
}

let point: Point3D = {
    x: 1,
    y: 2,
    z: 3
}

// 元组(明确地知道有多少个数据)
let position: [number,number] = [3424.3424,244]
let position1: [number,number,string] = [3424.3424,244,'nafj']

// 类型推论
// 1.声明变量初始化时   2.决定函数返回时
let year = 2024 //自动推断为number
function he(num1: number,num2: number){ //返回值自动推论为number
    return num1+num2
}


let birthday = 20020222
console.log('birthday',Object(birthday))

// 类型断言
/**
 * 例如 ：
 * <a href='XXX' id='link' ></a>
 * const aLink = document.getElementById('link')    //aLink默认为HTMLElement
 * aLink.href   //获取不到
 * 
 * const aLink = document.getElementById('link') as HTMLAnchorElement
 * 这样就可以访问到a标签的href属性了
 */

// 字面量类型
let str1 = 'hello ts'
const str2 = 'hello ts' //str2是一个常量，它的值不能改变只能是'hello ts',所以它的类型为'hello ts'
let number1: 18 = 18
// 意义用于一组有明确的可选值的变量
// 如贪吃蛇游戏，只能选择上下左右四个方向：
function changeDirection(direction: ('up' | 'down' | 'left' | 'right')){
    return direction
}
changeDirection('up')

// 枚举：定义一组命名常量。它描述一个值，该值可以是这些明明常量中的一个
enum Direction{ up, down, left, right=10 }  // 可以赋值
function changeDirection2(direction: Direction){
    return direction
}
changeDirection2(Direction.up)  // 对象写法
changeDirection2(Direction.right)
// 字符串枚举
enum Direction2{ up='up', down='down', left='left', right='right'}  // 字符串枚举每个量都得有初始值

// any类型  typescript变为anyscript(失去了类型保护的优势)
// 被声明为any类型的量可以进行任意操作，不会有代码提示
let objAny: any ={
    x:0
}
objAny.a = 100  // 没有该元素 没报错
objAny()    // 被当作函数调用 没报错
let temp: number = objAny   // 被赋值给别的量 没报错

// typeof 在类型上下文中引用变量活属性的类型(类型查询)
// 根据已有变量的值，获取该值的类型，来简化类型书写
let p = { a: 1, b: 2 }
function information(param: { a:number, b:number }) {
    return param.a + param.b
}
function information2(param: typeof p){
    return param.a + param.b
}
let num: typeof p.a = 1
// typeof 出现在参数冒号后面所处的环境就在类型上下文(区别于js代码)
// typeof只能用来查询变量活属性的类型，无法查询其他形式的类型(比如函数类型)

